﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Windows.Controls;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.ServiceLocation;
using MyFramework.Common.Interfaces;

namespace MyFramework.Helpers
{
    /// <summary>
    /// An Helper Class For Prism
    /// </summary>
    public static class PrismHelper
    {
        #region Fields

        /// <summary>
        /// The Region Manager
        /// </summary>
        private static IRegionManager regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();

        #endregion

        /// <summary>
        /// Registers the view with region.
        /// </summary>
        /// <param name="regionName">Name of the region.</param>
        /// <param name="viewType">Type of the view.</param>
        public static void RegisterViewWithRegion(string regionName, Type viewType)
        {
            Contract.Assert(typeof(UserControl).IsAssignableFrom(viewType));
            regionManager.RegisterViewWithRegion(regionName, viewType);
        }

        /// <summary>
        /// Registers the view with region.
        /// </summary>
        /// <typeparam name="T">The view type.</typeparam>
        /// <param name="regionName">Name of the region.</param>
        public static void RegisterViewWithRegion<T>(string regionName)
            where T : UserControl
        {
            regionManager.RegisterViewWithRegion(regionName, typeof(T));
        }

        /// <summary>
        /// Associate a view with a region, using a delegate to resolve a concrete instance of the view.
        /// When the region get's displayed, this delegate will be called and the result will be added to the
        /// views collection of the region.
        /// </summary>
        /// <param name="regionName">Name of the region.</param>
        /// <param name="getContentDelegate">The delegate to determine the concrete instance of the view.</param>
        public static void RegisterViewWithRegion(string regionName, Func<object> getContentDelegate)
        {
            var result = getContentDelegate();
            if (result != null)
            {
                regionManager.RegisterViewWithRegion(regionName, () => result);
            }
        }

        /// <summary>
        /// Requests the navigate.
        /// </summary>
        /// <param name="regionName">Name of the region.</param>
        /// <param name="viewType">Type of the view.</param>
        public static void RequestNavigate(string regionName, Type viewType)
        {
            Contract.Assert(typeof(UserControl).IsAssignableFrom(viewType));
            var view = new Uri(viewType.Name, UriKind.Relative);
            regionManager.RequestNavigate(regionName, view);
        }

        /// <summary>
        /// Requests the navigate.
        /// </summary>
        /// <typeparam name="T">The view type.</typeparam>
        /// <param name="regionName">Name of the region.</param>
        public static void RequestNavigate<T>(string regionName)
            where T : UserControl
        {
            var view = new Uri(typeof(T).Name, UriKind.Relative);
            regionManager.RequestNavigate(regionName, view);
        }

        /// <summary>
        /// Removes all view by type from region.
        /// </summary>
        /// <param name="regionName">Name of the region.</param>
        /// <param name="viewType">Type of the view.</param>
        public static void RemoveAllViewByTypeFromRegion(string regionName, Type viewType)
        {
            try
            {
                var views = (from v in regionManager.Regions[regionName].Views where v.GetType() == viewType select v);
                foreach (var item in views)
                {
                    regionManager.Regions[regionName].Remove(item);
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Removes all view by data context from region.
        /// </summary>
        /// <param name="regionName">Name of the region.</param>
        /// <param name="viewModel">The view model.</param>
        public static void RemoveAllViewByDataContextFromRegion(string regionName, IViewModel viewModel)
        {
            try
            {
                var views = (from v in regionManager.Regions[regionName].Views where ((IView)v).DataContext == viewModel select v);
                foreach (var item in views)
                {
                    regionManager.Regions[regionName].Remove(item);
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Removes all view from region.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="regionName">Name of the region.</param>
        public static void RemoveAllViewFromRegion<T>(string regionName)
            where T : UserControl
        {
            try
            {
                foreach (var item in regionManager.Regions[regionName].Views)
                {
                    regionManager.Regions[regionName].Remove(item);
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Gets the views in region.
        /// </summary>
        /// <param name="regionName">Name of the region.</param>
        /// <returns></returns>
        public static UserControl[] GetViewsInRegion(string regionName)
        {
            List<UserControl> result = new List<UserControl>();
            var views = from v in regionManager.Regions[regionName].Views select v;
            foreach (UserControl view in views)
            {
                result.Add(view);
            }

            return result.ToArray();
        }

        /// <summary>
        /// Gets the type of the view by.
        /// </summary>
        /// <param name="regionName">Name of the region.</param>
        /// <param name="viewType">Type of the view.</param>
        /// <returns></returns>
        public static UserControl GetViewByType(string regionName, Type viewType)
        {
            try
            {
                return (UserControl)(from v in regionManager.Regions[regionName].Views where v.GetType() == viewType select v).FirstOrDefault();
            }
            catch (Exception e)
            {

                throw e;
            }
        }

        /// <summary>
        /// Gets the view by view model.
        /// </summary>
        /// <param name="regionName">Name of the region.</param>
        /// <param name="viewModel">The view model.</param>
        /// <returns></returns>
        public static UserControl GetViewByViewModel(string regionName, IViewModel viewModel)
        {
            try
            {
                return (UserControl)(from v in regionManager.Regions[regionName].Views where ((IView)v).DataContext == viewModel select v).FirstOrDefault();
            }
            catch (Exception e)
            {

                throw e;
            }
        }
    }
}
